package com.ruoyi.dm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.CollectFileStatusEnum;
import com.ruoyi.common.exception.DataRepeatException;
import com.ruoyi.common.utils.biz.BizModule;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.dm.component.AnalysisStrategyManager;
import com.ruoyi.dm.component.DataStrategyManager;
import com.ruoyi.dm.domain.CollectEstimateVO;
import com.ruoyi.dm.domain.po.ReanalysisCollectRecordPO;
import com.ruoyi.dm.domain.po.ReanalysisQueryParam;
import com.ruoyi.dm.domain.po.ReanalysisVO;
import com.ruoyi.dm.mapper.ReanalysisCollectRecordMapper;
import com.ruoyi.dm.service.IReanalysisCollectRecordService;
import com.ruoyi.utils.TranferUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class ReanalysisCollectRecordServiceImpl extends ServiceImpl<ReanalysisCollectRecordMapper, ReanalysisCollectRecordPO> implements IReanalysisCollectRecordService {
    @Autowired
    private IReanalysisCollectRecordService reanalysisCollectRecordService;

    @Autowired
    private AnalysisStrategyManager analysisStrategyManager;

    @Autowired
    private DataStrategyManager dataStrategyManager;

    @Override
    public IPage query(ReanalysisQueryParam queryParam) {

        LambdaQueryWrapper<ReanalysisCollectRecordPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasLength(queryParam.getFileName()),ReanalysisCollectRecordPO::getFileName,queryParam.getFileName());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getDataType()),ReanalysisCollectRecordPO::getDataType,queryParam.getDataType());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getFileType()),ReanalysisCollectRecordPO::getFileType,queryParam.getFileType());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getStatus()), ReanalysisCollectRecordPO::getStatus,queryParam.getStatus());
        queryWrapper.orderByDesc(ReanalysisCollectRecordPO::getFileDate);
        if (null != queryParam.getStartTime() && null!= queryParam.getEndTime()) {
            String start = DateUtil.format(queryParam.getStartTime(), "yyyyMM");
            String end = DateUtil.format(queryParam.getEndTime(), "yyyyMM");
            queryWrapper.between(ReanalysisCollectRecordPO::getFileDate,start,end);

        }
        IPage page = reanalysisCollectRecordService.page(queryParam.page(), queryWrapper);
        List<ReanalysisVO> objects = new ArrayList<>();
        for (Object airCollectRecordPO : page.getRecords()) {
            ReanalysisCollectRecordPO po = (ReanalysisCollectRecordPO) airCollectRecordPO;
            ReanalysisVO airCollectVO = TranferUtils.tranferReanalysisRecordPO(po);
            objects.add(airCollectVO);
        }
        page.setRecords(objects);
        return page;
    }

    @Override
    public List<String> uploadFile(MultipartFile[] files, String dataType, String type) throws DataRepeatException {

        //单个文件,如果重复,直接抛异常
        if (files.length==1) {
            String filename = files[0].getOriginalFilename();
            int num = this.checkRepeat(filename);
            if (num>0) {
                //存在 不处理
                throw new DataRepeatException();
            }
        }

        List<ReanalysisCollectRecordPO> list = new ArrayList<>(files.length);
        Date now = new Date();
        String midPath = "/origin/wind/"+dataType;
        String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+midPath;
        List<String> resList = new ArrayList<>();
        for (MultipartFile file : files) {
            String filename = file.getOriginalFilename();
            int num = this.checkRepeat(filename);
            if (num>0) {
                //存在 不处理
                resList.add(filename);
                continue;
            }
            ReanalysisCollectRecordPO recordPO = new ReanalysisCollectRecordPO();
            recordPO.setFileName(filename);
            recordPO.setFileType(type);
            recordPO.setDataType(dataType);
            recordPO.setFileSize(file.getSize());
            recordPO.setUploadTime(now);
            recordPO.setFilePath(midPath);
            recordPO.setStatus(CollectFileStatusEnum.FILE_WAIT.getCode());
            File parentPath = new File(fullPath);
            try {
                if (!parentPath.exists()) {
                    parentPath.mkdirs();
                }
                File path = new File(fullPath, filename);
                file.transferTo(path);
                //通过filename 获取 信息
                //选择数据策略,并进行相应的的特殊化处理
                dataStrategyManager.switchStrategy(type,null,null).makeupPo(recordPO);
                log.info("文件:{} 上传完成",path );
            }catch (Exception e) {
                log.error("文件保存异常",e);
                recordPO.setStatus(CollectFileStatusEnum.FILE_ERROR.getCode());
                recordPO.setFileDesc("保存异常，"+e.getMessage());
            }

            list.add(recordPO);
        }
        //保存到数据库
        reanalysisCollectRecordService.saveBatch(list);
        for (ReanalysisCollectRecordPO po : list) {
            //默认方法
            analysisStrategyManager.analysisReAnalysis(po, null,null,null,null);
        }
        return resList;
    }

    @Override
    public boolean delFile(Long id) {

        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName);
        wrapper.eq(ReanalysisCollectRecordPO::getId,id);
        ReanalysisCollectRecordPO po = reanalysisCollectRecordService.getOne(wrapper);
        String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+po.getFilePath()+"/"+ po.getFileName();
        new File(fullPath).delete();

        return reanalysisCollectRecordService.removeById(id);
    }

    @Override
    public boolean delBatch(Long[] delParam) {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ReanalysisCollectRecordPO::getId,delParam);
        queryWrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName);
        List<ReanalysisCollectRecordPO> pos = reanalysisCollectRecordService.list(queryWrapper);
        if (null != pos) {
            for (ReanalysisCollectRecordPO po : pos) {
                String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+po.getFilePath()+"/"+ po.getFileName();
                new File(fullPath).delete();
            }
        }
        return reanalysisCollectRecordService.remove(queryWrapper);
    }

    @Override
    public String download(Long id) {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName);
        wrapper.eq(ReanalysisCollectRecordPO::getId,id);
        ReanalysisCollectRecordPO po = reanalysisCollectRecordService.getOne(wrapper);
        String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT);
        return fullPath+po.getFilePath()+"/"+ po.getFileName();
    }

    @Override
    public String downloadBatch(Long[] ids) {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName);
        wrapper.in(ReanalysisCollectRecordPO::getId,ids);
        List<ReanalysisCollectRecordPO> list = reanalysisCollectRecordService.list(wrapper);
        String path = PathUtil.tmpModuleDir(BizModule.COLLECT)+"/"+ DateUtil.format(new Date(),"yyyyMMddHHmmss")+".zip";
        if (CollectionUtil.isNotEmpty(list)) {
            File[] toZipArr = new File[list.size()];
            for (int i = 0; i < list.size(); i++) {
                String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+list.get(i).getFilePath()+"/"+list.get(i).getFileName();
                toZipArr[i] = new File(fullPath);
            }
            ZipUtil.zip(new File(path), false, toZipArr);
        }
        return path;
    }

    @Override
    public boolean analysis(Long id, String method, Double lon, Double lat, Double hight) {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName,ReanalysisCollectRecordPO::getFileType);
        wrapper.eq(ReanalysisCollectRecordPO::getId,id);
        ReanalysisCollectRecordPO po = reanalysisCollectRecordService.getOne(wrapper);

        LambdaUpdateWrapper<ReanalysisCollectRecordPO> uw = new LambdaUpdateWrapper<>();
        uw.eq(ReanalysisCollectRecordPO::getId,id);
        uw.set(ReanalysisCollectRecordPO::getStatus,CollectFileStatusEnum.FILE_WAIT.getCode());
        reanalysisCollectRecordService.update(uw);

        analysisStrategyManager.analysisReAnalysis(po,method,lon,lat,hight);
        return true;
    }


    @Override
    public boolean analysisBatch(String[] ids, String method, Double lon, Double lat, Double hight) {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getFilePath,ReanalysisCollectRecordPO::getFileName,ReanalysisCollectRecordPO::getFileType);
        wrapper.in(ReanalysisCollectRecordPO::getId,ids);
        List<ReanalysisCollectRecordPO> list = reanalysisCollectRecordService.list(wrapper);
        LambdaUpdateWrapper<ReanalysisCollectRecordPO> uw = new LambdaUpdateWrapper<>();
        uw.in(ReanalysisCollectRecordPO::getId,ids);
        uw.set(ReanalysisCollectRecordPO::getStatus,CollectFileStatusEnum.FILE_WAIT.getCode());
        reanalysisCollectRecordService.update(uw);
        if (CollectionUtil.isNotEmpty(list)) {
            for (ReanalysisCollectRecordPO po : list) {
                analysisStrategyManager.analysisReAnalysis(po,method,lon,lat,hight);
            }
        }
        return true;
    }

    @Override
    public CollectEstimateVO lookRes(Long id) throws Exception {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getResFile);
        wrapper.eq(ReanalysisCollectRecordPO::getId,id);
        ReanalysisCollectRecordPO po = reanalysisCollectRecordService.getOne(wrapper);
        if (null != po && StringUtils.hasLength(po.getResFile())) {
            JSONObject jsonObject = JSON.parseObject(po.getResFile());
            CollectEstimateVO collectEstimateVO = new CollectEstimateVO();
            collectEstimateVO.setToal(jsonObject.getInteger("total"));
            collectEstimateVO.setError(jsonObject.getInteger("error"));
            return collectEstimateVO;
        }else {
            throw  new Exception("数据不存在或解析异常");
        }
    }

    @Override
    public String lookDetailRes(Long id) throws Exception {
        LambdaQueryWrapper<ReanalysisCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(ReanalysisCollectRecordPO::getResFile);
        wrapper.eq(ReanalysisCollectRecordPO::getId,id);
        ReanalysisCollectRecordPO po = reanalysisCollectRecordService.getOne(wrapper);
        if (null != po && StringUtils.hasLength(po.getResFile())) {
            JSONObject jsonObject = JSON.parseObject(po.getResFile());
            String logFile = jsonObject.getString("logFile");
            String content = FileUtil.readString(logFile,Charset.forName("UTF-8"));
            return content;
        }else {
            throw  new Exception("数据不存在或解析异常");
        }
    }

    @Override
    public int checkRepeat(String filename) {
        return this.getBaseMapper().selectRepeat(filename);
    }
}
